#region USINGS
using System;
using System.Data;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Threading;
using System.Windows.Forms;
using DevComponents.DotNetBar.Controls;
using PolePositionDesktop.WebService;
using GoogleEarthClasses.Entities;
using GoogleEarthClasses.Global;
using GoogleEarthClasses.Logic;
using System.Configuration;
using System.Text.RegularExpressions;
using System.ComponentModel;
using System.Net;
#endregion USINGS
namespace PolePositionDesktop
{
    public partial class Demo : DevComponents.DotNetBar.Office2007RibbonForm    
    {
        #region Global Vars
        protected List<EPoint> m_ServerPoints;
        protected List<EPoint> m_LocalPoints;

        bool m_ShowPolygons = false;
        bool m_ShowAssets = true;

        private List<EKmlFile> m_KMLItems = new List<EKmlFile>();
        bool _GoogleEarthUnloaded = false;
        Modes m_Mode = Modes.Server;
        SelectDatabase m_SelectDatabase = null;
        string m_SelectedFolder;
        int m_SelectedPositionId;
        string m_LastVersion;
        bool m_isUploading;
        protected string[] m_Colors;
        string m_CurrentDownloadUploadStatus ="";
        int m_CurrentDownloadUploadStatusPercent = 0;
        int m_CurrentDownloadUploadMax = 100;
        List<string> m_FoldersToMoveAfterUpload;
        #endregion


        public Demo()
        {
            InitializeComponent();
            // if connection OK!
            if (TestConnection())
            {
                LoadGoogleEarth();
                areasControl1.DownloadServerPolygonTypes();
                DownloadServerPoints();
                DirHelper.isDirectory(Constants.K_InboxPath);
                checkLastVersion();
                DownloadAvailableColors();
            }
        }
        
        #region FormEvents
        void Demo_FormClosing(object sender, System.Windows.Forms.FormClosingEventArgs e)
        {
            this.Text = "Closing application - Unloading Google Earth...";
            CloseGoogleEarth();
        }
        void Demo_FormClosed(object sender, System.Windows.Forms.FormClosedEventArgs e)
        {
            if (!_GoogleEarthUnloaded)
            {
                googleEarthViewPort1.Unload();
                _GoogleEarthUnloaded = true;
                this.Text = "Closing application...";
                Thread.Sleep(5000);
            }
            else
                Application.ExitThread();
        }
        /// <summary>
        /// On load resize all controls in tabs
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void Demo_Load(object sender, System.EventArgs e)
        {
            ResizeItems();
        }
        /// <summary>
        /// Onresize resize all itemsagain
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void Demo_Resize(object sender, System.EventArgs e)
        {
            ResizeItems();
        } 
        #endregion

        #region DownloadFIle
        /// <summary>
        /// Download the last version of mobiledevice
        /// </summary>
        public void DownloadLastVersion()
        {
            string _FileName;
            string _PathUrl;
            try
            {
                LabelStatus.Text = Constants.k_DownloadingText;

                #region Binary
                DirHelper.isDirectory(Constants.K_InboxBinary);

                _FileName = Constants.K_InboxBinary + Constants.k_DeployMobileBinaryControlLibrary;
                _PathUrl = Constants.k_UriDownloadFile + m_LastVersion + "/" + Constants.K_BinaryFolder + Constants.k_DeployMobileBinaryControlLibrary;
                DownloadFile(_FileName, _PathUrl);

                _FileName = Constants.K_InboxBinary + Constants.k_DeployMobileBinaryDatabase;
                _PathUrl = Constants.k_UriDownloadFile + m_LastVersion + "/" + Constants.K_BinaryFolder + Constants.k_DeployMobileBinaryDatabase;
                DownloadFile(_FileName, _PathUrl);

                _FileName = Constants.K_InboxBinary + Constants.k_DeployMobileBinaryDeviceLibrary;
                _PathUrl = Constants.k_UriDownloadFile + m_LastVersion + "/" + Constants.K_BinaryFolder + Constants.k_DeployMobileBinaryDeviceLibrary;
                DownloadFile(_FileName, _PathUrl);

                _FileName = Constants.K_InboxBinary + Constants.k_DeployMobileBinaryExecute;
                _PathUrl = Constants.k_UriDownloadFile + m_LastVersion + "/" + Constants.K_BinaryFolder + Constants.k_DeployMobileBinaryExecute;
                DownloadFile(_FileName, _PathUrl);

                _FileName = Constants.K_InboxBinary + Constants.k_DeployMobileBinaryProjectCommon;
                _PathUrl = Constants.k_UriDownloadFile + m_LastVersion + "/" + Constants.K_BinaryFolder + Constants.k_DeployMobileBinaryProjectCommon;
                DownloadFile(_FileName, _PathUrl);


                #endregion

                #region ZipFIles
                _FileName = Constants.K_InboxPath + Constants.k_DeployMobile;
                _PathUrl = Constants.k_UriDownloadFile + m_LastVersion + "/" + Constants.k_DeployMobile;
                DownloadFile(_FileName, _PathUrl);
                _FileName = Constants.K_InboxPath + Constants.k_DeployMobileVersion;
                _PathUrl = Constants.k_UriDownloadFile + m_LastVersion + "/" + Constants.k_DeployMobileVersion;
                DownloadFile(_FileName, _PathUrl);
                _FileName = Constants.K_InboxPath + Constants.k_DeployMobileFull;
                _PathUrl = Constants.k_UriDownloadFile + m_LastVersion + "/" + Constants.k_DeployMobileFull;
                DownloadFile(_FileName, _PathUrl);


                #endregion
            }
            catch (Exception ex)
            {
                ErrorManager.CreateDebug("DownloadLastVersion->\n" + ex.Message + "\n" + ex.StackTrace);
            }
            finally
            {
                LabelStatus.Text = "";
            }


        }
        private void DownloadFile(string _FileName, string _PathUrl)
        {
            WebClient _webClient = new WebClient();
            _webClient.DownloadFileAsync(new Uri(_PathUrl), _FileName);
            _webClient.DownloadProgressChanged += new DownloadProgressChangedEventHandler(_webClient_DownloadProgressChanged);
            _webClient.DownloadFileCompleted += new AsyncCompletedEventHandler(_webClient_DownloadFileCompleted);
        }
        void _webClient_DownloadFileCompleted(object sender, AsyncCompletedEventArgs e)
        {
            
            ProgressbarStatus.Value = 0;
        }
        void _webClient_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
        {
            ProgressbarStatus.Value = e.ProgressPercentage;
        } 
        #endregion

        #region DownloadImageByPoint
        /// <summary>
        /// Start the background process to download all images by selected point
        /// </summary>
        private void DownloadImageByPoint()
        {
            BackgroundWorker _TmpBackgroundWorker = new BackgroundWorker();
            _TmpBackgroundWorker.DoWork += new DoWorkEventHandler(_TmpBackgroundWorker_DoWork);

        }
        void _TmpBackgroundWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            EPoint _TempPoint = GetCurrentPosition(m_SelectedPositionId);
            CheckImagesAndDownload(_TempPoint, _TempPoint.HaveImages,0);
        }
        #endregion
        
        #region MOBILE DATABASE FUNCTIONS
        /// <summary>
        /// Clean Mobile Resources and download server points
        /// </summary>
        protected void CloseMobileConnection()
        {

            this.ProgressbarStatus.Value = 0;
            this.ButtonUploadToServer.Enabled = false; //Disable Upload to server button
            this.ButtonCloseMobileConnection.Enabled = false; // disable Close mobile connection button
            this.ButtonLocateDatabase.Enabled = true; //Enable Locate Database Button
            this.buttonIDownloadData.Enabled = true;
            backgroundWorkerUploadData.CancelAsync();
            DownloadServerPoints();
        }
        /// <summary>
        /// Load sdf points
        /// </summary>
        /// <returns></returns>
        protected bool LocateDatabase()
        {
            try
            {
                bool IsNew;
                bool CopyMobileVersion;
                CleanPhotosPanel();
                m_SelectDatabase = new SelectDatabase();
                m_SelectDatabase.ShowDialog();
                m_SelectedFolder = m_SelectDatabase.SelectedFolder;
                IsNew = m_SelectDatabase.IsNew;
                CopyMobileVersion = m_SelectDatabase.CopyMobileVersion;
                m_SelectDatabase.Dispose();

                if (String.IsNullOrEmpty(m_SelectedFolder))
                    return false;

                if (CopyMobileVersion)
                {
                    if (DirHelper.isDirectory(Constants.K_InboxBinary))
                    {
                        DirectoryInfo tmpSource = new DirectoryInfo(Constants.K_InboxBinary);
                        DirectoryInfo tmpDestination = new DirectoryInfo(m_SelectedFolder);
                        DirHelper.CopyFiles(tmpSource, tmpDestination, true);
                    }
                }
                RefreshMobileDatabasePoints(IsNew);
                UpdateDatasource();
                return true;
            }
            catch (Exception )
            {
                return false;
            }
        }
        private void RefreshMobileDatabasePoints(bool IsNewDatabase)
        {
            LocateDatabases m_LocateDatabase;
            m_LocateDatabase = new LocateDatabases();
            m_LocateDatabase.SDFDatabasesPath = DirHelper.GetSdfPath(m_SelectedFolder);
            if (!m_LocateDatabase.TestMobileConnection())
            {
                MessageBox.Show(Constants.k_MobileConnectionError);
                return;
            }
            if (IsNewDatabase)
            {
                m_LocateDatabase.CopyToOutbox();
                m_SelectedFolder = GetParentFolder(m_LocateDatabase.SDFDatabasesPath);
            }

            m_LocalPoints = m_LocateDatabase.Points;
            m_Mode = Modes.Local;
        }

        /// <summary>
        /// Insert Local points in central database
        /// </summary>
        protected void UploadToServer()
        {
            try
            {
                backgroundWorkerUploadData.RunWorkerAsync();
            }
            catch (Exception ex)
            {
                ErrorManager.CreateDebug("UploadToServer->\n" + ex.Message + "\n" + ex.StackTrace);
            }
        }
        #endregion MOBILE DATABASE FUNCTIONS

        #region Functions
        /// <summary>
        /// Load Altitude, Logitude, Latitude in details panel
        /// </summary>
        /// <param name="_Longitude">Longitude point</param>
        /// <param name="_Altitude">Altitude point</param>
        /// <param name="_Latitude">Latitude point</param>
        protected void LoadDetailsInPanel(string _Longitude, string _Altitude, string _Latitude, string _Color, string _Description, string _Satellites, string _Angle)
        {
            LabelLatitude.Text = _Latitude;
            LabelAltitude.Text = _Altitude;
            LabelLongitude.Text = _Longitude;
            txtDescription.Text =_Description;
            txtSatellites.Text = _Satellites;
            txtAngle.Text = _Angle;
            DropDownColors.SelectedItem = _Color;
        }
        /// <summary>
        /// Clean Details panel, put Longitude,Latitude,Altitude in ""
        /// </summary>
        protected void CleanDetailsPanel()
        {
            LabelLatitude.Text = "";
            LabelAltitude.Text = "";
            LabelLongitude.Text = "";
            txtDescription.Text = "";
            txtSatellites.Text = "";
            txtAngle.Text = "";

            if(DropDownColors.Items.Count>0) DropDownColors.SelectedIndex = 0;
       
        }
        /// <summary>
        /// Test Central Database Connection
        /// </summary>
        /// <returns></returns>
        protected bool TestConnection()
        {
            //Test Connection to the server
            bool StatusConnection = Server.TestConnection();
            if (StatusConnection)
                ButtonTestConnection.Image = global::PolePositionDesktop.Properties.Resources.TestServer_Ok;
            else
                ButtonTestConnection.Image = global::PolePositionDesktop.Properties.Resources.TestServer_Fail;
            return StatusConnection;
        }
        /// <summary>
        /// Download central server points and update datagrid
        /// </summary>
        protected void DownloadData()
        {
            m_ServerPoints = null;
            DownloadServerPoints();
        }
        /// <summary>
        /// Create KML file with selected Points
        /// </summary>
        protected void ViewSelected()
        {
            EPoint _Point = null;
            GEHelper.ClearPointTypes(ref m_KMLItems);
            switch (m_Mode)
            {
                case Modes.Server:
                    foreach (DataGridViewRow dr in DataGridList.SelectedRows)
                    {
                        _Point = GetCurrentPosition(ConvertHelper.ToInt32(dr.Cells["DataGridListIdPosition"].Value));
                        GESetNewPoint(_Point.LocationId.ToString(), _Point.Latitude.ToString(), _Point.Longitude.ToString(), _Point.Altitude.ToString(), _Point.Description,  _Point.Images , _Point.Color);
                    }
                    break;
                case Modes.Local:
                    foreach (DataGridViewRow dr in DataGridList.SelectedRows)
                    {
                        _Point = GetCurrentPosition(ConvertHelper.ToInt32(dr.Cells["DataGridListIdPosition"].Value));
                        //TODO: check why it is calling GetImagesByPositionId(_Point.LocationId)
                        GESetNewPoint(_Point.LocationId.ToString(), _Point.Latitude.ToString(), _Point.Longitude.ToString(), _Point.Altitude.ToString(), _Point.Description, GetImagesByPositionId(_Point.LocationId), _Point.Color);
                    }
                    break;
            }
            WriteKMLFileAndOpenGE();
        }
        /// <summary>
        /// Create KML file with all points
        /// </summary>
        protected void ViewAll()
        {
            GEHelper.ClearPointTypes(ref m_KMLItems);
            if (m_ShowAssets)
            {
                List<EPoint> _tmpList = null;
                switch (m_Mode)
                {
                    case Modes.Server:
                        _tmpList = m_ServerPoints;
                        break;
                    case Modes.Local:
                        _tmpList = m_LocalPoints;
                        break;
                }

                foreach (EPoint _Point in _tmpList)
                    GESetNewPoint(_Point.LocationId.ToString(), _Point.Latitude.ToString(), _Point.Longitude.ToString(), _Point.Altitude.ToString(), _Point.Description, _Point.Images, _Point.Color);
            }
            WriteKMLFileAndOpenGE();
        }
        /// <summary>
        /// get a list of images filteres by a position Id
        /// </summary>
        /// <param name="IdPosition"></param>
        /// <returns></returns>
        protected List<EImage> GetImagesByPositionId(Int32 IdPosition)
        {
            List<EImage> _ListEimages = new List<EImage>();
            bool found = false;
            string _PointDirectory;
            if (m_Mode == Modes.Local)
            {
                if (m_LocalPoints != null)
                {
                    for (int j = 0; j < m_LocalPoints.Count && !found; j++)
                    {
                        if (m_LocalPoints[j].LocationId == IdPosition)
                        {
                            _ListEimages = m_LocalPoints[j].Images;
                            found = true;
                        }
                    }
                }
            }
            else
            {
                if (m_ServerPoints != null)
                {
                    _PointDirectory = GImages.CheckingImageFolder(IdPosition);
                    DirectoryInfo _dir = new DirectoryInfo(Constants.K_ImageCachePath + _PointDirectory + "//");
                    FileInfo[] _ImageFiles = _dir.GetFiles();
                    Regex _ValidateFileForPoint = new Regex("^" + IdPosition + "_[0-9]\\.jpeg$");
                    EImage _TempImage;
                    foreach (FileInfo _ImageFile in _ImageFiles)
                    {
                        if (_ValidateFileForPoint.Match(_ImageFile.Name).Success)
                        {
                            _TempImage = new EImage();
                            _TempImage.ContentPath = _ImageFile.FullName;
                            //TODO: ADD THE IMAGE ID --> IF NOT IS NOT POSSIBLE TO DELETE IMAGE
                            //_TempImage.ImageId =
                            _ListEimages.Add(_TempImage); 
                        }
                        else
                            DownloadImageByPoint();
                    }
                }               
            }
            return _ListEimages;
        }
        /// <summary>
        /// Focus in TABMap
        /// </summary>
        protected void ActivateTabMap()
        {
            if (this.TabMainContainer.SelectedTabIndex != (Int32)Tabs.Map)
                this.TabMainContainer.SelectedTabIndex = (Int32)Tabs.Map;
        }
        /// <summary>
        /// call ServiceMangaer and get the last version in m_version Global var
        /// </summary>
        private void checkLastVersion()
        {
            try
            {
                m_LastVersion = WebServiceManager.GetLastVersion();
                labelVersion.Text = m_LastVersion;
                if (!CompareVersion())
                {
                    DownloadLastVersion();
                    DirHelper.DeleteFiles(new DirectoryInfo(Constants.K_InboxPath));
                }

            }
            catch (Exception ex)
            {
                ErrorManager.CreateDebug("checkLastVersion->\n" + ex.InnerException + "\n" + ex.StackTrace);
            }
        }
        private bool CompareVersion()
        {
            if (File.Exists(Constants.K_InboxPath + Constants.k_DeployMobileVersion))
            {
                string[] _Lines = File.ReadAllLines(Constants.K_InboxPath + Constants.k_DeployMobileVersion);
                if (string.IsNullOrEmpty(_Lines[0]))
                {
                    return false;
                }
                else
                {
                    if (_Lines[0] == m_LastVersion)
                        return true;
                }
            }
            else
            {
                File.Create(Constants.K_InboxPath + Constants.k_DeployMobileVersion);
            }
            return false;

            
        }
        /// <summary>
        /// resize all tabs items
        /// </summary>
        private void ResizeItems()
        {
            this.DataGridList.Size = new Size(this.DataGridList.Size.Width, TabMainContainer.Height - 50);
            this.panelViewLocalPhotos.Size = new Size(this.panelViewLocalPhotos.Size.Width, TabMainContainer.Height - 80);
            googleEarthViewPort1.GoogleEarth_Resize(this.Width, tabControlPanel1.Height);
            this.areasControl1.Size = new Size(this.areasControl1.Width, TabMainContainer.Height - 50);
            tabAssetEditSearch.Size = new Size(this.tabAssetEditSearch.Width, TabMainContainer.Height - 50);
        }
        /// <summary>
        /// clears all the photos in panel
        /// </summary>
        private void CleanPhotosPanel()
        {
            this.panelViewLocalPhotos.Controls.Clear();
        }
        /// <summary>
        /// Return a Epoint entity by Position
        /// </summary>
        /// <param name="IdPosition"></param>
        /// <returns></returns>
        private EPoint GetCurrentPosition(Int32 IdPosition)
        {
            List<EPoint> _Points;

            if (m_Mode == Modes.Local)
                _Points = m_LocalPoints;
            else
                _Points = m_ServerPoints;
            foreach (EPoint _Point in _Points)
            {
                if (_Point.LocationId == IdPosition)
                    return _Point;
            }
            return null;
        }
        /// <summary>
        /// get the parent folder by any folder
        /// </summary>
        /// <param name="file"></param>
        /// <returns></returns>
        protected string GetParentFolder(string file)
        {
            FileInfo f = new FileInfo(file);
            return f.DirectoryName;
        }
        #endregion
        #region DataList&DataSource
        #region POSITIONS TABLES
        private void DataGridList_SelectionChanged(object sender, System.EventArgs e)
        {
            try
            {
                DataGridView _DataGridSelected = (DataGridView)sender;
                EPoint _Point = null;
                if (_DataGridSelected.SelectedRows.Count <= 0) return;
                CleanDetailsPanel();
                CleanPhotosPanel();
                m_SelectedPositionId = Convert.ToInt32(_DataGridSelected["DataGridListIdPosition", _DataGridSelected.SelectedRows[0].Index].Value);
                _Point = GetCurrentPosition(m_SelectedPositionId);
                if (_Point != null)
                {
                    LoadDetailsInPanel(_Point.Longitude.ToString(), _Point.Altitude.ToString(), _Point.Latitude.ToString(), _Point.Color, _Point.Description, _Point.Satellites.ToString(), _Point.Angle.ToString());
                    if (_Point.HaveImages > 0)
                        LoadLocalImagesInPanel(_Point);
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        private void DataGridList_CellClick(object sender, System.Windows.Forms.DataGridViewCellEventArgs e)
        {
            DataGridView _DataGridSelected = (DataGridView)sender;
            if (_DataGridSelected.SelectedRows.Count <= 0)
            {
                return;
            }
            EPoint _Point;
            m_SelectedPositionId = Convert.ToInt32(_DataGridSelected["DataGridListIdPosition", _DataGridSelected.SelectedRows[0].Index].Value);
            _Point = GetCurrentPosition(m_SelectedPositionId);
            this.googleEarthViewPort1.FlyTo(_Point.Latitude, _Point.Longitude, _Point.Altitude);
            ActivateTabMap();
        }
        private void DataGridList_DataSourceChanged(object sender, System.EventArgs e)
        {
            switch (m_Mode)
            {   
                case Modes.Server:
                    this.DataGridList.AllowUserToDeleteRows = false;
                    break;
                case Modes.Local:
                    this.DataGridList.AllowUserToDeleteRows = true;
                    break;
            }
            DataGridList.Update();
        }
        private void bindingSourcePoints_DataSourceChanged(object sender, System.EventArgs e)
        {
            try
            {
                DataGridList.DataSource = bindingSourcePoints;
                DataGridList.Update();
                //SINCE THE DATASOURCE HAS CHANGED, I WILL REDRAW ALL THE GE POINTS
                ViewAll(); 
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        private void UpdateDatasource()
        {
            try
            {
                switch (m_Mode)
                {
                    case Modes.Server:
                        bindingSourcePoints.DataSource = m_ServerPoints;
                        break;
                    case Modes.Local:
                        bindingSourcePoints.DataSource = m_LocalPoints;
                        break;
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        private void DataGridList_DataError(object sender, DataGridViewDataErrorEventArgs e)
        {
            try
            {
                MessageBox.Show(e.Exception.Message);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        #endregion POSITIONS TABLES
        
        #endregion
        #region ButtonActions
        private void ButtonTestConnection_Click(object sender, EventArgs e)
        {
            TestConnection();
        }
        private void ButtonLocateDatabase_Click(object sender, EventArgs e)
        {
            if (LocateDatabase())
            {
                this.ButtonCloseMobileConnection.Enabled = true; //Enable close mobile connection
                this.ButtonUploadToServer.Enabled = true;//Enable upload to server;
                this.buttonIDownloadData.Enabled = false;
                this.ButtonLocateDatabase.Enabled = false;
                m_Mode = Modes.Local;
            }
        }
        private void ButtonUploadToServer_Click(object sender, EventArgs e)
        {
            UploadToServer();
        }
        private void buttonIDownloadData_Click(object sender, EventArgs e)
        {
            DownloadData();
        }
        private void ButtonViewAll_Click(object sender, EventArgs e)
        {
            m_ShowAssets = true;
            ViewAll();
            ActivateTabMap(); 
        }
        private void ButtonViewSelected_Click(object sender, EventArgs e)
        {
            ViewSelected();
            ActivateTabMap(); 
        }
        private void ButtonCloseMobileConnection_Click(object sender, EventArgs e)
        { 
            CloseMobileConnection();
        }
        private void LabelStatus_Click(object sender, EventArgs e)
        {
            DialogResult tmpDialogResult;
            if (m_isUploading)
            {
                tmpDialogResult = MessageBox.Show(Constants.k_stopProcessText, "", MessageBoxButtons.YesNo);
                switch (tmpDialogResult)
                {
                    case DialogResult.No:
                        break;
                    case DialogResult.Yes:
                        backgroundWorkerUploadData.CancelAsync();
                        break;
                }

            }
        }


        #endregion ButtonActions
        #region GoogleEarthFunctions
        /// <summary>
        /// start google earth
        /// </summary>
        protected void LoadGoogleEarth()
        {
            this.googleEarthViewPort1.Start();            
        }
        protected void CloseGoogleEarth()
        {
            ClearGEData();
            tmrCloseGE.Enabled = true;
            this.Text = "Closing application - Unloading Google Earth...";
        }
        private void tmrCloseGE_Tick(object sender, EventArgs e)
        {
            if (!_GoogleEarthUnloaded)
            {
                googleEarthViewPort1.Unload();
                _GoogleEarthUnloaded = true;
                this.Text = "Closing application...";
            }
            else
                Application.ExitThread();
        }
        private void WriteKMLFileAndOpenGE()
        {
            #region HOLD POSITION
            ThirdPartyLibraries.CurrentPosition _CurrentPosition = googleEarthViewPort1.GetCurrentCameraPosition();
            if(_CurrentPosition.Longitude !=0)
                GEHelper.UpdateCurrentPositon(ref m_KMLItems, _CurrentPosition.Altitude, _CurrentPosition.Latitude, _CurrentPosition.Longitude, _CurrentPosition.Range, _CurrentPosition.Tilt, _CurrentPosition.AltitudeMode);
            #endregion HOLD POSITION

            //GENERATES THE COMPLETE STRING OF THE KML FILE TO BE LOADED IN GE
            string _KMLCode = GEHelper.GenerateKMLFile(ref m_KMLItems);
            GEHelper.WriteKMLFile(_KMLCode, Constants.k_Filename);
            googleEarthViewPort1.OpenKmlFile(Constants.k_Filename, 1);
        }
        protected void ClearGEData()
        {
            string _EmptyKML = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><kml xmlns=\"http://earth.google.com/kml/2.1\"></kml>";
            GEHelper.WriteKMLFile(_EmptyKML, Constants.k_Filename);
        }
        
        #region LOAD POINTS IN GOOGLE EARTH
        /// <summary>
        /// ADDS A NEW POINT TO THE EKmlFile LIST, INCLUDING A FIELD WITH THE COMPLETE KML CODE
        /// </summary>
        private void GESetNewPoint(string _Name, string _Latitude, string _Longitude, string _Altitude, string _Description, List<EImage> Images, string _Color)
        {
            EKmlFile _KMLItem;
            string _Code;
            _Code = GEHelper.GeneratePlacemark(_Name, _Latitude, _Longitude, _Altitude, _Description, Images, _Color);
            _KMLItem = new EKmlFile(TypeKMLOfElement.Point, _Name, _Code);
            m_KMLItems.Add(_KMLItem);
        }
        private string ConvertToDegrees(string number)
        {
            try
            {
                string _Position = "";

                string[] _Number = number.Split(",".ToCharArray());
                int _StartPosition = 2;
                switch (_Number[0].Length)
                {
                    case 4:
                        _StartPosition = 2;
                        break;
                    case 5:
                        _StartPosition = 3;
                        break;
                    case 6:
                        _StartPosition = 4;
                        break;
                }

                if (number.StartsWith("-"))
                    _Position = number.Substring(0, _StartPosition) + "." + number.Substring(_StartPosition);
                else
                    _Position = number.Substring(0, _StartPosition) + "." + number.Substring(_StartPosition);
                return _Position.Replace(",", ".");

            }
            catch (Exception ex)
            {
                string error = "ConvertToDegrees->" + number + ex.Message + "";
                ErrorManager.CreateDebug(error);
                return "";
            }

        }
        #endregion LOAD POINTS IN GOOGLE EARTH
        #endregion
        #region TimerActions
        void TestConnectionTimer_Tick(object sender, EventArgs e)
        {
            TestConnection();
        }

        #endregion
        #region Server
        protected void DownloadServerPoints()
        {
            Server _Server = new Server();
            _Server.LoadServerPoints();
            m_ServerPoints = _Server.Points;
            m_Mode = Modes.Server;
            RefreshServerImagesPaths();
            UpdateDatasource();
            m_ShowAssets = true;
            //ViewAll();
            if(!this.backgroundWorkerDownloadImages.IsBusy) 
                this.backgroundWorkerDownloadImages.RunWorkerAsync();
        }
        private void RefreshServerImagesPaths() {
            string _fileName;
            string _tmpDirectory;
            foreach (EPoint _Asset in m_ServerPoints) {
                _tmpDirectory = GImages.CheckingImageFolder(_Asset.LocationId);
                foreach (EImage _Image in _Asset.Images) {
                    _fileName = _Asset.LocationId.ToString() + "_" + _Image.ImageId.ToString() + ".jpeg";
                    _Image.ContentPath = Constants.K_ImageCachePath + _tmpDirectory + "\\" + _fileName;
                
                }
            }
        }
        #endregion
        #region Photos
        protected void LoadLocalImagesInPanel(EPoint Asset)
        {
            PictureBox _PhotoPreview = null;
            Int32 i;
            Point[] _Locations = LoadPictureBoxPositions();
            CleanPhotosPanel(); //Before include Picture box in panel, clear them
            for (i = 0; i < Asset.Images.Count; i++)
            {
                if (File.Exists(Asset.Images[i].ContentPath))
                {
                    _PhotoPreview = new PictureBox();
                    _PhotoPreview.Location = _Locations[i];
                    _PhotoPreview.Size = new Size(160, 120);
                    _PhotoPreview.SizeMode = PictureBoxSizeMode.StretchImage;
                    _PhotoPreview.Image = Image.FromFile(Asset.Images[i].ContentPath);
                    if (m_Mode == Modes.Server)
                        _PhotoPreview.Click += new EventHandler(_PhotoPreview_Click);
                    this.panelViewLocalPhotos.Controls.Add(_PhotoPreview);

                }
            }
        }
        void _PhotoPreview_Click(object sender, EventArgs e)
        {
            WebBrowser webBrowser = new WebBrowser();
            webBrowser.Navigate("about:blank");
            HtmlDocument doc = webBrowser.Document;
            HtmlWindow _window = doc.Window;
            _window.Open(new Uri(Constants.k_ImagesUrl + m_SelectedPositionId.ToString() + "&Width=" + Constants.k_ThumbailWidth.ToString() + ""), "displayWindow", "status=yes,width=800,height=400", false);
        }
        private Point[] LoadPictureBoxPositions()
        {
            
            Point[] pbxPositions = new Point[4];
            pbxPositions[0] = new Point(9, 16);
            pbxPositions[1] = new Point(184, 16);
            pbxPositions[2] = new Point(9, 139);
            pbxPositions[3] = new Point(184, 139);
            return pbxPositions;
        }

        #endregion
        #region BackGroundWorker

        #region UploadPositionImages
        void backgroundWorkerUploadData_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
        {
            try
            {
                m_isUploading = true;
                m_FoldersToMoveAfterUpload = new List<string>();
                string _Dir = m_SelectedFolder;
                while (_Dir != "")
                {
                    UploadAssetsAndImages(_Dir, e);
                    if (backgroundWorkerUploadData.CancellationPending)
                    {
                        e.Cancel = true;
                        return;
                    }
                    m_FoldersToMoveAfterUpload.Add(_Dir);
                    _Dir = DirHelper.getNextDirectory(_Dir, m_FoldersToMoveAfterUpload);
                }
                MessageBox.Show("Upload process completed succesfully");
            }
            catch (Exception ex)
            {
                ErrorManager.CreateDebug("backgroundWorkerUploadData_DoWork->\n" + ex.Message + "\n" + ex.StackTrace);
                MessageBox.Show("Upload process was unsuccesful. Please try again or contact the administrator");
            }

        }
        void UploadAssetsAndImages(string _Dir, System.ComponentModel.DoWorkEventArgs e)
        {
            LocateDatabases m_locateDatabase = new LocateDatabases();
            m_locateDatabase.SDFDatabasesPath = DirHelper.GetSdfPath(_Dir);
            List<EPoint> m_points = m_locateDatabase.Points;
            Int32 IdPositionIserted;
            Service1 WebService = new Service1();
            int CounterPoint = 0;
            int _Total = 0;
            foreach (EPoint Point in m_points)
            {
                _Total += Point.HaveImages;
            }
            foreach (EPoint _Point in m_points)
            {
                if (backgroundWorkerUploadData.CancellationPending)
                {
                    e.Cancel = true;
                    return;
                }
                if (_Point.InsertedPosition == Int32.MinValue)
                {
                    IdPositionIserted = WebService.PositionInsert(_Point.Longitude, _Point.Latitude, _Point.Altitude, _Point.Description, _Point.SatelliteTime, _Point.Satellites, _Point.Angle, _Point.Color);
                    m_locateDatabase.UpdateInsertedPosition(_Point.LocationId, IdPositionIserted);
                    System.Threading.Thread.Sleep(ConvertHelper.ToInt32(ConfigurationManager.AppSettings["TimeWaitUpPositiosn"]));
                }else{
                    IdPositionIserted = _Point.InsertedPosition;
                    WebService.PositionImageDeleteAll(IdPositionIserted);
                }
                #region UPLOAD IMAGES FOR SPECIFIC POINT
                foreach (EImage _Image in _Point.Images)
                {
                    if (backgroundWorkerUploadData.CancellationPending)
                    {
                        e.Cancel = true;
                        return;
                    }
                    #region STATISTICS
                    m_CurrentDownloadUploadStatus = "Uploading " + CounterPoint.ToString() + " / " + _Total.ToString();
                    m_CurrentDownloadUploadStatusPercent = (int)((100 * CounterPoint) / _Total);
                    this.backgroundWorkerUploadData.ReportProgress(m_CurrentDownloadUploadStatusPercent);
                    m_CurrentDownloadUploadMax = _Total;
                    #endregion
                    WebService.PositionImageInsert(IdPositionIserted, _Image.Name, _Image.ImageBytes);
                    System.Threading.Thread.Sleep(ConvertHelper.ToInt32(ConfigurationManager.AppSettings["TimeWaitUpImages"]));
                    CounterPoint++;
                }
                #endregion UPLOAD IMAGES FOR SPECIFIC POINT
                m_locateDatabase.CompleteInsertedPosition(_Point.LocationId);
            }
        }
        void backgroundWorkerUploadData_ProgressChanged(object sender, System.ComponentModel.ProgressChangedEventArgs e)
        {
            ProgressbarStatus.Maximum = 100;
            ProgressbarStatus.Tooltip = m_CurrentDownloadUploadStatus + " (" + e.ProgressPercentage.ToString() + "%)";
            ProgressbarStatus.Value = m_CurrentDownloadUploadStatusPercent;
            ProgressbarStatus.Refresh();
            ButtonUploadToServer.Enabled = false;
            LabelStatus.Text = Constants.k_UploadingPointsText;
        }
        void backgroundWorkerUploadData_RunWorkerCompleted(object sender, System.ComponentModel.RunWorkerCompletedEventArgs e)
        {
            #region RESET LABELS AND VARIABLES
            m_isUploading = false;
            LabelStatus.Text = "";
            ProgressbarStatus.Value = 0;
            m_CurrentDownloadUploadMax = 0;
            m_CurrentDownloadUploadStatus = "";
            m_CurrentDownloadUploadStatusPercent = 0;
            ButtonUploadToServer.Enabled = true;
            CleanPhotosPanel();
            #endregion RESET LABELS AND VARIABLES
            #region MOVE FINISHED DATABASE, AND CONTINUE WITH THE NEXT FOLDER
            DirectoryInfo _SourceDirectory;
            DirectoryInfo _DestinationDirectory;
            foreach (string _FolderSource in m_FoldersToMoveAfterUpload)
            {
                _SourceDirectory = new DirectoryInfo(_FolderSource);
                _DestinationDirectory = new DirectoryInfo(_FolderSource.Replace(Constants.K_OutboxName, Constants.K_SentName));
                DirHelper.CopyFiles(_SourceDirectory, _DestinationDirectory, true);
                try
                {
                    _SourceDirectory.Delete(true);
                }
                catch { }
            }
            #endregion MOVE FINISHED DATABASE, AND CONTINUE WITH THE NEXT FOLDER
            //AFTER FINISHING UPLOADING, I CLOSE THE MOBILE CONNECTION.
            CloseMobileConnection();
        }
        #endregion

        #region DownloadImages
        void backgroundWorkerDownloadImages_ProgressChanged(object sender, System.ComponentModel.ProgressChangedEventArgs e)
        {
            this.ProgressbarStatus.Maximum = 100;
            this.ProgressbarStatus.Tooltip =m_CurrentDownloadUploadStatus + " ("+ e.ProgressPercentage.ToString() + "%)";
            this.ProgressbarStatus.Value = m_CurrentDownloadUploadStatusPercent;
            this.ProgressbarStatus.Refresh();
            LabelStatus.Text = Constants.k_DownloadImages;
        }
        /// <summary>
        /// THIS FUNCTION STARTS THE CHECKING IMAGES BACKGROUND PROCESS
        /// CHECKS IF THE IMAGES EXISTS, AND IF NOT THEY ARE DOWNLOADED INTO THE Image-Cache FOLDER
        /// </summary>
        void backgroundWorkerDownloadImages_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
        {
            try
            {
                CheckingImageStatus();
            }
            catch (Exception ex)
            {
                ErrorManager.CreateDebug("CheckingImageStatus->\n" + ex.Message +"\n" + ex.StackTrace);
            }
        }
        void backgroundWorkerDownloadImages_RunWorkerCompleted(object sender, System.ComponentModel.RunWorkerCompletedEventArgs e)
        {
            m_CurrentDownloadUploadMax = 0;
            m_CurrentDownloadUploadStatus = "";
            m_CurrentDownloadUploadStatusPercent = 0;
            this.ProgressbarStatus.Value = 0;            
            this.LabelStatus.Text = "";
        }
        
        private void CheckingImageStatus()
        {

            DirHelper.isDirectory(Constants.K_ImageCachePath);
            Int32 _PendingAmountTotal;
            Int32 _PendingAmountLeft = 0;
            _PendingAmountTotal = CheckTotalAmountPendingImages();
            m_CurrentDownloadUploadMax = _PendingAmountTotal;
            foreach (EPoint _Point in m_ServerPoints)
            {
                if (_Point.HaveImages > 0) {
                    _PendingAmountLeft = CheckImagesAndDownload(_Point , _PendingAmountTotal, _PendingAmountLeft);
                }
            }
            m_CurrentDownloadUploadStatus = "";
        }
        private Int32 CheckImagesAndDownload(EPoint Point, int PendingAmountTotal, int PendingAmountLeft)
        {
            int _foundCounter = 0;
            string _fileName = "";
            string _tmpDirectory;
            foreach(EImage _Image in Point.Images)
            {
                _tmpDirectory = GImages.CheckingImageFolder(Point.LocationId);
                _fileName = Point.LocationId.ToString() + "_" + _Image.ImageId.ToString() + ".jpeg";
                _Image.ContentPath = Constants.K_ImageCachePath + _tmpDirectory + "\\" + _fileName;
                if (!File.Exists(_Image.ContentPath))
                {
                    m_CurrentDownloadUploadStatus = "Downloading " + PendingAmountLeft.ToString() + " / " + PendingAmountTotal.ToString();
                    WebServiceManager.DownloadImage(Point.LocationId, _Image.ImageId, _Image.ContentPath);
                    #region STATISTICS FOR PROGRESS BAR
                    PendingAmountLeft++;
                    m_CurrentDownloadUploadStatusPercent = (int)((100 * PendingAmountLeft) / PendingAmountTotal);
                    this.backgroundWorkerDownloadImages.ReportProgress(m_CurrentDownloadUploadStatusPercent);
                    #endregion STATISTICS FOR PROGRESS BAR
                }                
                _foundCounter++;
            }
            return PendingAmountLeft;
        }
        private Int32 CheckTotalAmountPendingImages() {
            Int32 _PendingAmount=0;
            string _fileName = "";
            string _tmpDirectory;
            foreach (EPoint _Point in m_ServerPoints){
                if (_Point.HaveImages > 0){
                    foreach(EImage _Image in _Point.Images){
                        _tmpDirectory = GImages.CheckingImageFolder(_Point.LocationId);
                        _fileName = _Point.LocationId.ToString() + "_" + _Image.ImageId.ToString() + ".jpeg";
                        if (!File.Exists(Constants.K_ImageCachePath + _tmpDirectory + "\\" + _fileName))
                            _PendingAmount++;

                    }
                }
            }
            return _PendingAmount;
        }
        #endregion

        private void BarStatus_ItemClick(object sender, EventArgs e)
        {
            if(!String.IsNullOrEmpty(m_CurrentDownloadUploadStatus)) 
                MessageBox.Show(m_CurrentDownloadUploadStatus);
        }

        #endregion
        #region COLORS
        void DownloadAvailableColors()
        {
            m_Colors = WebServiceManager.GetColors();
            foreach (string _color in m_Colors)
            {
                DropDownColors.Items.Add((object)_color);
            }
        }
        #endregion 
        #region POLYGONS
        private void ButtonViewPolygons_Click(object sender, EventArgs e)
        {
            m_ShowPolygons = !m_ShowPolygons;
            areasControl1.ViewPolygons(m_ShowPolygons, ref m_KMLItems);
            WriteKMLFileAndOpenGE();
            if (m_ShowPolygons)
                ButtonViewPolygons.Image = global::PolePositionDesktop.Properties.Resources.ShowPolygons_Yellow;
            else
                ButtonViewPolygons.Image = global::PolePositionDesktop.Properties.Resources.ShowPolygons;
        }
        #endregion POLYGONS
        #region ASSETS NEW, EDIT REMOVE
        private void OpenAssetForm(ActionType ActionType, EPoint Asset) {
            try
            {
                CleanPhotosPanel();
                foreach(Control _Control in this.panelViewLocalPhotos.Controls)
                    _Control.Dispose();
                AssetForm _AssetForm;
                _AssetForm = new AssetForm();
                _AssetForm.ActionType = ActionType;
                _AssetForm.Asset = Asset;
                _AssetForm.Mode = m_Mode;
                _AssetForm.SDFDatabaseFolder = m_SelectedFolder;
                _AssetForm.Colors = m_Colors;
                _AssetForm.ShowDialog();
                if (_AssetForm.ActionCompleted)
                {
                    if (m_Mode == Modes.Server)
                    {
                        UpdateAssetList(_AssetForm.Asset, ActionType);
                    }
                    else
                        RefreshMobileDatabasePoints(false);

                    bindingSourcePoints.ResetBindings(false);
                }             
            }
            catch (FormatException ex)
            {
                MessageBox.Show(Constants.k_FormatIncorret + "\n" + ex.Message);
            }
            catch (Exception ex)
            {
                ErrorManager.CreateDebug("OpenAssetForm->\n" + ex.Message + "\n" + ex.StackTrace);
            }
        }
        private void UpdateAssetList(EPoint Asset, ActionType SelectedActionType) {
            switch (SelectedActionType) { 
                case ActionType.Delete: 
                    m_ServerPoints.Remove(Asset);
                    break;
                case ActionType.Edit:
                    EPoint _Asset = GetCurrentPosition(m_SelectedPositionId);
                    _Asset = Asset;
                    break;
                case ActionType.New:
                    m_ServerPoints.Add(Asset);
                    break;
            }
            if (SelectedActionType != ActionType.Delete) {
                if (!this.backgroundWorkerDownloadImages.IsBusy)
                    this.backgroundWorkerDownloadImages.RunWorkerAsync();
            }
        }
        private void buttonEditAsset_Click(object sender, EventArgs e)
        {
            EPoint _Asset = GetCurrentPosition(m_SelectedPositionId);
            OpenAssetForm(ActionType.Edit, _Asset);
        }
        private void buttonNewAsset_Click_1(object sender, EventArgs e)
        {
            EPoint _Asset = new EPoint();
            OpenAssetForm(ActionType.New, _Asset);
        }
        private void buttonDeleteAsset_Click_1(object sender, EventArgs e)
        {
            EPoint _Asset = GetCurrentPosition(m_SelectedPositionId);
            OpenAssetForm(ActionType.Delete, _Asset);
        }
        #endregion ASSETS NEW, EDIT REMOVE

        #region DIRECTIONS
        private void buttonDirections_Click(object sender, EventArgs e)
        {
            if (DataGridList.SelectedRows.Count != 2){
                MessageBox.Show("There must be 2 assets selected to get directions");
                return;
            }
            Int32 _SourcePointId;
            EPoint _SourcePoint;
            Int32 _DestinationPointId;
            EPoint _DestinationPoint;
            _SourcePointId = Convert.ToInt32(DataGridList["DataGridListIdPosition", DataGridList.SelectedRows[0].Index].Value);
            _DestinationPointId = Convert.ToInt32(DataGridList["DataGridListIdPosition", DataGridList.SelectedRows[1].Index].Value);
           
            _SourcePoint = GetCurrentPosition(_SourcePointId);
            _DestinationPoint = GetCurrentPosition(_DestinationPointId);

            //http://maps.google.com/maps?f=d&hl=en&saddr=39.50448678,-103.974954751667&daddr=39.5059683833333,-103.978393263333&om=1&output=kml
            string _WebAddress = Constants.K_GoogleMapDirectionsKML;
            _WebAddress = _WebAddress.Replace("KML_SOURCE_LATITUDE", _SourcePoint.Latitude.ToString().Replace(",","."));
            _WebAddress = _WebAddress.Replace("KML_SOURCE_LONGITUDE", _SourcePoint.Longitude.ToString().Replace(",","."));

            _WebAddress = _WebAddress.Replace("KML_DESTINATION_LATITUDE", _DestinationPoint.Latitude.ToString().Replace(",","."));
            _WebAddress = _WebAddress.Replace("KML_DESTINATION_LONGITUDE", _DestinationPoint.Longitude.ToString().Replace(",", "."));

            
            string _KMLString;
            string _Directions;
            int _StartingIndex;
            _KMLString = readHtmlPage(_WebAddress);
            if (string.IsNullOrEmpty(_KMLString)){
                MessageBox.Show("Direction for the selected points where not found.");
                return;
            }
            _StartingIndex = _KMLString.IndexOf("<Document>") + "<Document>".Length;
            _Directions = _KMLString.Substring(_StartingIndex, _KMLString.Length - _StartingIndex);

            _StartingIndex = _Directions.IndexOf("</Document>");
            _Directions = _Directions.Substring(0, _StartingIndex);
            EKmlFile _KMLDirections = new EKmlFile();
            _KMLDirections.GUID = "1";
            _KMLDirections.KMLCode = _Directions;
            _KMLDirections.TypeKMLElement = TypeKMLOfElement.Direction;
            m_KMLItems.Add(_KMLDirections);
            WriteKMLFileAndOpenGE();
            //http://maps.google.com/maps?f=d&hl=en&saddr=KML_SOURCE_LATITUDE,KML_SOURCE_LONGITUDE&daddr=KML_DESTINATION_LATITUDE,KML_DESTINATION_LONGITUDE&om=1&output=kml
        }
        private String readHtmlPage(string url)
        {
            String result;
            WebResponse objResponse;
            WebRequest objRequest = System.Net.HttpWebRequest.Create(url);
            objResponse = objRequest.GetResponse();
            using (StreamReader sr =
               new StreamReader(objResponse.GetResponseStream()))
            {
                result = sr.ReadToEnd();
                // Close and clean up the StreamReader
                sr.Close();
            }
            return result;
        }
        private void buttonDirectionsFromHQ_Click(object sender, EventArgs e)
        {
            if (DataGridList.SelectedRows.Count != 1){
                MessageBox.Show("There must be 1 asset selected to get directions from headquarter");
                return;
            }
            
            Int32 _DestinationPointId;
            EPoint _DestinationPoint;
            _DestinationPointId = Convert.ToInt32(DataGridList["DataGridListIdPosition", DataGridList.SelectedRows[0].Index].Value);
            _DestinationPoint = GetCurrentPosition(_DestinationPointId);

            //http://maps.google.com/maps?f=d&hl=en&saddr=39.50448678,-103.974954751667&daddr=39.5059683833333,-103.978393263333&om=1&output=kml
            string _WebAddress = Constants.K_GoogleMapDirectionsHQKML;
            _WebAddress = _WebAddress.Replace("KML_SOURCE_HQ", Constants.K_GoogleMapDirectionsHQAddress);
            
            _WebAddress = _WebAddress.Replace("KML_DESTINATION_LATITUDE", _DestinationPoint.Latitude.ToString().Replace(",","."));
            _WebAddress = _WebAddress.Replace("KML_DESTINATION_LONGITUDE", _DestinationPoint.Longitude.ToString().Replace(",", "."));

            
            string _KMLString;
            string _Directions;
            int _StartingIndex;
            _KMLString = readHtmlPage(_WebAddress);
            if (string.IsNullOrEmpty(_KMLString))
            {
                MessageBox.Show("Direction for the selected points where not found.");
                return;
            }
            _StartingIndex = _KMLString.IndexOf("<Document>") + "<Document>".Length;
            _Directions = _KMLString.Substring(_StartingIndex, _KMLString.Length - _StartingIndex);

            _StartingIndex = _Directions.IndexOf("</Document>");
            _Directions = _Directions.Substring(0, _StartingIndex);
            EKmlFile _KMLDirections = new EKmlFile();
            _KMLDirections.GUID = "1";
            _KMLDirections.KMLCode = _Directions;
            _KMLDirections.TypeKMLElement = TypeKMLOfElement.Direction;
            m_KMLItems.Add(_KMLDirections);
            WriteKMLFileAndOpenGE();
            //http://maps.google.com/maps?f=d&hl=en&saddr=KML_SOURCE_LATITUDE,KML_SOURCE_LONGITUDE&daddr=KML_DESTINATION_LATITUDE,KML_DESTINATION_LONGITUDE&om=1&output=kml
        }
        private void buttonHideDirections_Click_1(object sender, EventArgs e)
        {
            GEHelper.ClearDirectionsTypes(ref m_KMLItems);
            WriteKMLFileAndOpenGE();
        }
        #endregion DIRECTIONS
        private void googleEarthViewPort1_Leave(object sender, EventArgs e)
        {
            googleEarthViewPort1.HideBalloon();
        }

        private void buttonShowPoint_Click_1(object sender, EventArgs e)
        {
            m_ShowAssets = !m_ShowAssets;
            ViewAll();
            if (m_ShowAssets)
                buttonShowPoint.Image = global::PolePositionDesktop.Properties.Resources.ShowPoints_Yellow;
            else
                buttonShowPoint.Image = global::PolePositionDesktop.Properties.Resources.ShowPoints;

        }

        private void buttonSetParent_Click(object sender, EventArgs e)
        {
            if (DataGridList.SelectedRows.Count != 2)
            {
                MessageBox.Show("There must be 2 assets selected to set the parent");
                return;
            }
            Int32 _PointId;
            EPoint _Point;
            Int32 _ParentPointId;
            _PointId = Convert.ToInt32(DataGridList["DataGridListIdPosition", DataGridList.SelectedRows[0].Index].Value);
            _ParentPointId = Convert.ToInt32(DataGridList["DataGridListIdPosition", DataGridList.SelectedRows[1].Index].Value);
            _Point = GetCurrentPosition(_PointId);
            _Point.ParentPoint = new EPoint(_ParentPointId);
            #region SAVE PARENT ON SERVER
            WebService.Service1 _WebService;
            _WebService = new Service1();
            _WebService.SetParent(_PointId, _ParentPointId);
            #endregion SAVE PARENT ON SERVER
            DrawLineBetweenPoints();
        }
        private void DrawLineBetweenPoints() {
            GEHelper.ClearLinesTypes(ref m_KMLItems);
            EPoint _DestinationPoint;
            EKmlFile _KMLLine;
            if (m_Mode == Modes.Server)
            {
                #region GENERATE LINE STYLE
                EKmlFile _KMLLineStyle = new EKmlFile();
                _KMLLineStyle.GUID = "1";
                _KMLLineStyle.KMLCode = GEHelper.GenerateLineStyle();
                _KMLLineStyle.TypeKMLElement = TypeKMLOfElement.Line;
                m_KMLItems.Add(_KMLLineStyle);
                #endregion GENERATE LINE STYLE
                foreach (EPoint _Point in m_ServerPoints)
                {
                    if (_Point.ParentPoint != null)
                    {
                        if (_Point.ParentPoint.LocationId != int.MinValue)
                        {
                            _DestinationPoint = GetCurrentPosition(_Point.ParentPoint.LocationId);
                            _KMLLine = new EKmlFile();
                            _KMLLine.GUID = "1";
                            _KMLLine.KMLCode = GEHelper.GenerateLine(_Point.Latitude.ToString(), _Point.Longitude.ToString(), _DestinationPoint.Latitude.ToString(), _DestinationPoint.Longitude.ToString());
                            _KMLLine.TypeKMLElement = TypeKMLOfElement.Line;
                            m_KMLItems.Add(_KMLLine);
                            WriteKMLFileAndOpenGE();
                        }
                    }
                }
            }
        }

        private void googleEarthViewPort1_ChangePositionClicked(object sender, ThirdPartyLibraries.CurrentPositionArgs _CurrentPositionArgs)
        {
            if(m_Mode == Modes.Server)
            {
                ThirdPartyLibraries.CurrentPosition _CurrentPosition = _CurrentPositionArgs.GetCurrentPosition();
                EPoint _Point = SearchPointByLatLon(_CurrentPosition);
                if(m_StartAssigningParent)
                {
                    if(_Point != null){
                        if(m_PointChild == null){
                            m_PointChild = _Point;
                            MessageBox.Show("Selected child: " + m_PointChild.LocationId.ToString() +  "\n Select Parent");
                        }else{
                            if (m_PointChild.LocationId != _Point.LocationId)
                            {
                                m_PointChild.ParentPoint = _Point;
                                UpdateExistingPoint(m_PointChild);
                                m_StartAssigningParent = false;
                                MessageBox.Show("Selected child: " + m_PointChild.LocationId.ToString() + "\n Selected Parent:" + m_PointChild.ParentPoint.LocationId.ToString());

                                #region SAVE PARENT ON SERVER
                                WebService.Service1 _WebService;
                                _WebService = new Service1();
                                _WebService.SetParent(m_PointChild.LocationId, m_PointChild.ParentPoint.LocationId);
                                #endregion SAVE PARENT ON SERVER
                                DrawLineBetweenPoints();
                                m_PointChild = null;
                            }
                        }
                    }
                    
                }
            }
        }
        private void UpdateExistingPoint(EPoint Point) {
            foreach (EPoint _Point in m_ServerPoints) {
                if (_Point.LocationId == Point.LocationId) {
                    _Point.ParentPoint = Point.ParentPoint;
                }
            }
        }

        private EPoint SearchPointByLatLon(ThirdPartyLibraries.CurrentPosition CurrentPosition)
        {
            EPoint _PointTemp=null;
            double _PointsDistance;
            double _PointsDistanceMin = 10;
            foreach (EPoint _Point in m_ServerPoints) {
                _PointsDistance = distance(_Point.Latitude,_Point.Longitude,CurrentPosition.Latitude,CurrentPosition.Longitude,'K');
                if (_PointsDistance < _PointsDistanceMin)
                {
                    _PointsDistanceMin = _PointsDistance;
                    _PointTemp = _Point;
                }
            }
            return _PointTemp;
        }
        bool m_StartAssigningParent = false;
        EPoint m_PointChild;
        private void buttonItemAssignParent_Click(object sender, EventArgs e)
        {
            m_StartAssigningParent = true;
        }
        #region DISTANCE CALCULATOR
        private double distance(double lat1, double lon1, double lat2, double lon2, char unit)
        {
            double theta = lon1 - lon2;
            double dist = Math.Sin(deg2rad(lat1)) * Math.Sin(deg2rad(lat2)) + Math.Cos(deg2rad(lat1)) * Math.Cos(deg2rad(lat2)) * Math.Cos(deg2rad(theta));
            dist = Math.Acos(dist);
            dist = rad2deg(dist);
            dist = dist * 60 * 1.1515;
            if (unit == 'K')
            {
                dist = dist * 1.609344;
            }
            else if (unit == 'N')
            {
                dist = dist * 0.8684;
            }
            return (dist);
        }

        //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
        //::  This function converts decimal degrees to radians             :::
        //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
        private double deg2rad(double deg)
        {
            return (deg * Math.PI / 180.0);
        }

        //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
        //::  This function converts radians to decimal degrees             :::
        //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
        private double rad2deg(double rad)
        {
            return (rad / Math.PI * 180.0);
        }
        #endregion DISTANCE CALCULATOR

        private void buttonAbout_Click(object sender, EventArgs e)
        {
            System.Deployment.Application.ApplicationDeployment _App;
            if (System.Deployment.Application.ApplicationDeployment.IsNetworkDeployed) 
            {
                System.Deployment.Application.ApplicationDeployment ad = System.Deployment.Application.ApplicationDeployment.CurrentDeployment;
                MessageBox.Show("Version: " +  ad.CurrentVersion.Revision.ToString());
            }
        }
    }
}